package com.redepronik.negosysfab.invfac.report;


import static com.redepronik.negosys.utils.Utils.iva;
import static com.redepronik.negosys.utils.Utils.redondearTotales;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.redepronik.negosys.invfac.entity.Detalleegreso;
import com.redepronik.negosys.invfac.entity.Egreso;
import com.redepronik.negosys.invfac.entity.Local;
import com.redepronik.negosys.invfac.entity.Producto;
import com.redepronik.negosys.invfac.entity.Tipodocumento;
import com.redepronik.negosys.invfac.entityAux.CantidadFactura;
import com.redepronik.negosys.invfac.entityAux.ChequeReporte;
import com.redepronik.negosys.invfac.entityAux.CobroFacturaReporte;
import com.redepronik.negosys.invfac.entityAux.CobroFacturaReporteAuxiliar;
import com.redepronik.negosys.invfac.entityAux.EgresoReporte;
import com.redepronik.negosys.invfac.entityAux.EntregaProductoReporte;
import com.redepronik.negosys.invfac.entityAux.FacturaReporte;
import com.redepronik.negosys.invfac.entityAux.GananciaFacturaReporte;
import com.redepronik.negosys.invfac.entityAux.PersonaCedulaNombre;
import com.redepronik.negosys.invfac.entityAux.VolumenVentaFactura;
import com.redepronik.negosys.invfac.entityAux.VolumenVentaProducto;
import com.redepronik.negosys.invfac.service.EgresoService;
import com.redepronik.negosys.invfac.service.MoraService;
import com.redepronik.negosys.invfac.service.ProductoService;
import com.redepronik.negosys.rrhh.entity.Ciudad;
import com.redepronik.negosys.rrhh.entity.Persona;
import com.redepronik.negosys.rrhh.entity.Provincia;
import com.redepronik.negosys.rrhh.service.CiudadService;
import com.redepronik.negosys.rrhh.service.ClienteService;
import com.redepronik.negosys.rrhh.service.EmpleadoService;
import com.redepronik.negosys.rrhh.service.PersonaService;
import com.redepronik.negosys.rrhh.service.ProvinciaService;
import com.redepronik.negosys.utils.configuraciones.NumerosPorLetras;
import com.redepronik.negosys.utils.service.ReporteService;

@Controller
@Scope("session")
public class EgresoReport {

	@Autowired
	private ReporteService reporteService;

	@Autowired
	private PersonaService personaService;

	@Autowired
	private ClienteService clienteService;

	@Autowired
	private EgresoService egresoService;

	@Autowired
	private ProvinciaService provinciaService;

	@Autowired
	private CiudadService ciudadService;

	@Autowired
	private MoraService moraService;

	@Autowired
	private ProductoService productoService;

	@Autowired
	private EmpleadoService empleadoService;

	private List<Provincia> listaProvincias;
	private List<Ciudad> listaCiudades;

	private Local local;
	private Date fechaInicio;
	private Date fechaFin;
	private Provincia provincia;
	private Ciudad ciudad;
	private Tipodocumento tipodocumento;

	private List<Egreso> listaEgresoSeleccionado;
	private List<Egreso> listaEgresos;
	private List<PersonaCedulaNombre> listaVendedores;
	private int vendedorId;
	private int ordenarId;

	public int getOrdenarId() {
		return ordenarId;
	}

	public void setOrdenarId(int ordenarId) {
		this.ordenarId = ordenarId;
	}

	public EgresoReport() {
		listaEgresoSeleccionado = new ArrayList<Egreso>();
		ciudad = new Ciudad();
		provincia = new Provincia();
		listaCiudades = new ArrayList<Ciudad>();
		local = new Local();
		tipodocumento = new Tipodocumento();
	}

	public void cargarCiudades() {
		if (provincia.getProvinciaid() != 0) {
			listaCiudades = new ArrayList<Ciudad>();
			listaCiudades = ciudadService.obtenerPorProvincia(provincia);
		}
	}

	public Ciudad getCiudad() {
		return ciudad;
	}

	public Date getFechaFin() {
		return fechaFin;
	}

	public Date getFechaInicio() {
		return fechaInicio;
	}

	public List<Ciudad> getListaCiudades() {
		return listaCiudades;
	}

	public List<Egreso> getListaEgresos() {
		return listaEgresos;
	}

	public List<Egreso> getListaEgresoSeleccionado() {
		return listaEgresoSeleccionado;
	}

	public List<Provincia> getListaProvincias() {
		return listaProvincias;
	}

	public List<PersonaCedulaNombre> getListaVendedores() {
		return listaVendedores;
	}

	public Local getLocal() {
		return local;
	}

	public Provincia getProvincia() {
		return provincia;
	}

	public Tipodocumento getTipodocumento() {
		return tipodocumento;
	}

	public int getVendedorId() {
		return vendedorId;
	}

	@PostConstruct
	public void init() {
		listaProvincias = provinciaService.obtener();
		listaVendedores = empleadoService.obtenerPorCargo(5);
	}

	public void limpiarObjetosBusqueda() {
		fechaInicio = null;
		fechaFin = null;
		ciudad = new Ciudad();
		provincia = new Provincia();
		local = new Local();
		listaEgresos = new ArrayList<Egreso>();
	}

	public void obtenerEgresos() {
		if (fechaInicio == null)
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA", "INGRESE UNA FECHA DE INICIO"));
		else if (fechaFin == null)
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA", "INGRESE UNA FECHA DE FIN"));
		else if (local.getLocalid() == 0)
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA", "ESCOJA UN LOCAL"));
		else if (provincia.getProvinciaid() == 0)
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA", "ESCOJA UNA PROVINCIA"));
		else if (ciudad.getCiudadid() == 0)
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA", "ESCOJA UNA CIUDAD"));
		else
			listaEgresos = egresoService.obtenerEntregaProducto(fechaInicio,
					fechaFin, local, ciudad);
	}

	private void presentaMensaje(FacesMessage message) {
		FacesContext.getCurrentInstance().addMessage(null, message);
	}

	private List<EntregaProductoReporte> quicksort(
			List<EntregaProductoReporte> list, int iz, int de) {
		if (iz >= de)
			return list;
		int i = iz;
		int d = de;
		if (iz != de) {
			EntregaProductoReporte epr;
			int pivote = iz;
			while (iz != de) {
				while (list.get(de).getNombre()
						.compareToIgnoreCase(list.get(pivote).getNombre()) >= 0
						&& i < de)
					de--;
				while (list.get(iz).getNombre()
						.compareToIgnoreCase(list.get(pivote).getNombre()) < 0
						&& i < de)
					iz++;
				if (de != iz) {
					epr = list.get(de);
					list.set(de, list.get(iz));
					list.set(iz, epr);
				}
				if (iz == de) {
					quicksort(list, i, iz - 1);
					quicksort(list, iz + 1, d);
				}
			}
		}
		return list;
	}

	public void reporteChequesPorCobrar(ActionEvent actionEvent) {
		List<ChequeReporte> list = egresoService
				.obtenerChequesPorCobrarPorFechas(fechaInicio, fechaFin);
		fechaInicio = null;
		fechaFin = null;
		Map<String, Object> parametro = new HashMap<String, Object>();
		reporteService.generarReportePDF(list, parametro, "ChequesPorCobrar");
	}

	public void reporteCobranzaFactura(ActionEvent actionEvent) {
		boolean bn = false;
		List<CobroFacturaReporte> list = new ArrayList<CobroFacturaReporte>();
		for (Persona persona : clienteService
				.obtenerPersonasPorFacturasPendientes(ciudad.getCiudadid(),
						vendedorId)) {
			bn = true;
			List<CobroFacturaReporteAuxiliar> list1 = new ArrayList<CobroFacturaReporteAuxiliar>();
			for (Egreso egreso : egresoService.obtenerPorEstado(
					persona.getCedula(), 9, null, null, null)) {
				BigDecimal total = egresoService.calcularTotal(egreso);
				BigDecimal abono = egresoService.calcularEntradas(egreso);

				list1.add(new CobroFacturaReporteAuxiliar(egreso
						.getFechainicio(), egreso.getCodigodocumento(),
						redondearTotales(total.subtract(abono))));
			}
			list.add(new CobroFacturaReporte(persona.getCliente().getFolio(),
					persona.getApellido() + " " + persona.getNombre(), persona
							.getDireccion(), persona.getReferencia(), list1));
		}
		if (bn) {
			String nombre = "";
			if (vendedorId != 0) {
				Persona p = empleadoService
						.obtenerPorEmpleadoCargoId(vendedorId).getEmpleado()
						.getPersona();
				nombre = p.getApellido() + " " + p.getNombre();
			}
			Map<String, Object> parametro = new HashMap<String, Object>();
			parametro.put("COBRADOR", nombre);
			parametro.put("CIUDAD",
					ciudadService.obtenerPorCiudadId(ciudad.getCiudadid())
							.getNombre());
			reporteService
					.generarReportePDF(list, parametro, "CobranzaFactura");
		} else
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA", "NO TIENE FACTURAS POR COBRAR"));
	}

	public void reporteEntregaProducto(ActionEvent actionEvent) {
		if (listaEgresoSeleccionado.isEmpty())
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA",
					"ESCOJA UNA FACTURA PARA GENERAR EL REPORTE"));
		else {
			List<Detalleegreso> listDetalleEgreso = new ArrayList<Detalleegreso>();
			for (Egreso egreso : listaEgresoSeleccionado)
				listDetalleEgreso.addAll(egresoService
						.duplicarDetalleEgreso(egreso.getDetalleegresos()));

			for (Detalleegreso detalleegreso : listDetalleEgreso)
				detalleegreso.setEliminar(true);

			List<Detalleegreso> listDetalleEgresoFinal = egresoService
					.sumarCantidades(listDetalleEgreso);

			List<EntregaProductoReporte> list = new ArrayList<EntregaProductoReporte>();

			for (Detalleegreso de : listDetalleEgresoFinal) {
				Producto producto = productoService.obtenerPorProductoId(de
						.getProducto().getProductoid());

				String nombrecantidad = productoService.convertirUnidadString(
						de.getCantidad(), producto.getProductounidads());

				list.add(new EntregaProductoReporte(producto.getEan(), producto
						.getNombreimprimir(), de.getCantidad(), nombrecantidad));
			}

			Map<String, Object> parametro = new HashMap<String, Object>();
			parametro.put("fechInicio", fechaInicio);
			parametro.put("fechFin", fechaFin);
			parametro.put("CIUDAD",
					ciudadService.obtenerPorCiudadId(ciudad.getCiudadid())
							.getNombre());
			reporteService.generarReportePDF(
					quicksort(list, 0, list.size() - 1), parametro,
					"EntregaProducto");
		}
	}

	public void reporteFactura(Egreso egreso, Persona persona,
			CantidadFactura cantidadFactura,
			List<FacturaReporte> listFacturaReporte) {
		List<EgresoReporte> list = new ArrayList<EgresoReporte>();

		String telefono = "";
		if (persona.getTelefonopersonas() != null
				&& !persona.getTelefonopersonas().isEmpty())
			telefono = persona.getTelefonopersonas().get(0).getTelefono();

		list.add(new EgresoReporte(egreso, persona, telefono, NumerosPorLetras
				.convertNumberToLetter(cantidadFactura.getTotal()),
				egresoService.redondearCantidadFactura(new CantidadFactura(),
						cantidadFactura), listFacturaReporte));
		Map<String, Object> parametro = new HashMap<String, Object>();
		reporteService.generarReportePDF(list, parametro, "Factura");
	}

	public void reporteGanancia(ActionEvent actionEvent) {
		List<GananciaFacturaReporte> list = egresoService
				.obtenerGananciaPorFechas(fechaInicio, fechaFin, 9,
						iva.getPorcentaje());
		fechaInicio = null;
		fechaFin = null;
		Map<String, Object> parametro = new HashMap<String, Object>();
		reporteService.generarReportePDF(list, parametro, "Ganancia");

	}

	public void reporteNotaEntrega(Egreso egreso, Persona persona,
			CantidadFactura cantidadFactura,
			List<FacturaReporte> listFacturaReporte) {
		List<EgresoReporte> list = new ArrayList<EgresoReporte>();

		String telefono = "";
		if (persona.getTelefonopersonas() != null
				&& !persona.getTelefonopersonas().isEmpty())
			telefono = persona.getTelefonopersonas().get(0).getTelefono();

		list.add(new EgresoReporte(egreso, persona, telefono, NumerosPorLetras
				.convertNumberToLetter(cantidadFactura.getTotal()),
				egresoService.redondearCantidadFactura(new CantidadFactura(),
						cantidadFactura), listFacturaReporte));
		Map<String, Object> parametro = new HashMap<String, Object>();
		reporteService.generarReportePDF(list, parametro, "NotaEntrega");
	}

	public void reporteVolumenVentaFactura(ActionEvent actionEvent) {
		if (fechaInicio != null && fechaFin != null
				&& tipodocumento.getTipodocumentoid() != 0) {
			List<Egreso> list1 = egresoService
					.obtenerPorFechasAndTIpoDocumentoAndVendedor(fechaInicio,
							fechaFin, tipodocumento.getTipodocumentoid(),
							vendedorId);

			List<VolumenVentaFactura> list = new ArrayList<VolumenVentaFactura>();

			for (Egreso egreso : list1)
				list.add(new VolumenVentaFactura(egreso.getFechainicio(),
						egreso.getCodigodocumento(), egresoService
								.calcularTotal(egreso)));

			String nombre = "";
			if (vendedorId != 0) {
				Persona p = empleadoService
						.obtenerPorEmpleadoCargoId(vendedorId).getEmpleado()
						.getPersona();
				nombre = p.getApellido() + " " + p.getNombre();
			}

			Map<String, Object> parametro = new HashMap<String, Object>();
			parametro.put("fechInicio", fechaInicio);
			parametro.put("fechFin", fechaFin);
			parametro.put("VENDEDOR", nombre);
			fechaInicio = null;
			fechaFin = null;
			reporteService.generarReportePDF(list, parametro,
					"VolumenVentaFactura");
		}
	}

	public void reporteVolumenVentaProducto(ActionEvent actionEvent) {
		if (fechaInicio != null && fechaFin != null) {
			List<VolumenVentaProducto> list = new ArrayList<VolumenVentaProducto>();

			for (VolumenVentaProducto vvp : egresoService
					.obtenerVolumenVentaProducto(fechaInicio, fechaFin,
							ordenarId)) {
				Producto p = productoService.obtenerPorProductoId(vvp.getId());
				list.add(new VolumenVentaProducto(vvp.getId(), vvp.getEan(),
						vvp.getNombre(), vvp.getCantidad(), productoService
								.convertirUnidadString(vvp.getCantidad(),
										p.getProductounidads())));
			}

			Map<String, Object> parametro = new HashMap<String, Object>();
			parametro.put("fechInicio", fechaInicio);
			parametro.put("fechFin", fechaFin);
			fechaInicio = null;
			fechaFin = null;
			reporteService.generarReportePDF(list, parametro,
					"VolumenVentaProducto");
		}
	}

	public void setCiudad(Ciudad ciudad) {
		this.ciudad = ciudad;
	}

	public void setFechaFin(Date fechaFin) {
		this.fechaFin = fechaFin;
	}

	public void setFechaInicio(Date fechaInicio) {
		this.fechaInicio = fechaInicio;
	}

	public void setListaCiudades(List<Ciudad> listaCiudades) {
		this.listaCiudades = listaCiudades;
	}

	public void setListaEgresos(List<Egreso> listaEgresos) {
		this.listaEgresos = listaEgresos;
	}

	public void setListaEgresoSeleccionado(List<Egreso> listaEgresoSeleccionado) {
		this.listaEgresoSeleccionado = listaEgresoSeleccionado;
	}

	public void setListaProvincias(List<Provincia> listaProvincias) {
		this.listaProvincias = listaProvincias;
	}

	public void setListaVendedores(List<PersonaCedulaNombre> listaVendedores) {
		this.listaVendedores = listaVendedores;
	}

	public void setLocal(Local local) {
		this.local = local;
	}

	public void setProvincia(Provincia provincia) {
		this.provincia = provincia;
	}

	public void setTipodocumento(Tipodocumento tipodocumento) {
		this.tipodocumento = tipodocumento;
	}

	public void setVendedorId(int vendedorId) {
		this.vendedorId = vendedorId;
	}

}